﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace DisplayBoardInfo.Client.Forms
{
    public partial class Client : Form
    {
        private AddPatient addPatientForm;
        private EditPatient editPatientForm;
        private Network.Messages.Content.User user;
        private NetworkClientClass networkCC;
        private Network.Messages.Content.AppointmentArgs appointmentArgs;
        private IEnumerable<Network.Messages.Content.Appointment> appointmentsFromServer;
        private string reason;
        private bool changes = false;

        public Client(Network.Messages.Content.User user, NetworkClientClass ncc)
        {
            InitializeComponent();
            this.user = user;
            this.networkCC = ncc;
            networkCC.C.MessageRecived += new Network.Client.MessageRecivedHandler(MessageRecived);
            this.patientsLV.FullRowSelect = true;
            this.editButton.Enabled = false;
            this.deleteButton.Enabled = false;
            this.stopButton.Enabled = true;
            this.ktoZalogowany.Text = "Jesteś zalogowany/(a) jako "
                + user.Username + ".";
            this.photoPanel.BackgroundImage = user.Photo;
            this.imieNazwiskoLekarza.Text = "Dr " + user.Name + " " + user.Lastname;
            this.calendar.MaxSelectionCount = 1;
            this.getAppointments(DateTime.Now);
            this.infoLabel.Text = "Witaj, wyświetlona lista dotyczy dnia dzisiejszego. Aby wybrać innny dzień skorzystaj z kalendarza.";
            this.infoLabel.Text += " Aby rozpocząć pracę, kliknij na przycisk Początek pracy.";
        }

        void MessageRecived(object sender, Network.MessageEventArgs args)
        {
            try
            {
                Network.Messages.NetworkMessage recieved = args.Message;
                if (recieved.Type == Network.Messages.NetworkMessageTypes.Appointments)
                {
                    this.appointmentsFromServer = (IEnumerable<Network.Messages.Content.Appointment>)recieved.Content;
                    this.Invoke((MethodInvoker)delegate()
                    {
                        this.patientsLV.Items.Clear();
                    }); 
                    foreach (Network.Messages.Content.Appointment appointment in this.appointmentsFromServer)
                    {
                        this.Invoke((MethodInvoker)delegate()
                        {
                            this.addPatientMethod(appointment.Number.ToString(), appointment.Patient.Name,
                            appointment.Patient.LastName, appointment.Date, appointment.ExpectedTime, appointment.ID, appointment.Patient.PESEL);
                        });
                    }
                }
                if (recieved.Type == Network.Messages.NetworkMessageTypes.OK)
                {
                    MessageBox.Show(recieved.Content.ToString());          
                }
                if (recieved.Type == Network.Messages.NetworkMessageTypes.Error)
                {
                    MessageBox.Show(recieved.Content.ToString());
                }
                else
                {
                    // dostałem nie to czego się spodziewałem
                }
            }
            catch (Exception e)
            {
                MessageBox.Show(e.Message.ToString());
                throw;
            }
        }

        private void getAppointments(DateTime time)
        {
            this.appointmentArgs = new Network.Messages.Content.AppointmentArgs();
            this.appointmentArgs.Date = time;
            this.appointmentArgs.ConnectedWithDoctor = this.user.Username;
            this.networkCC.C.Send(new Network.Messages.NetworkMessage(Network.Messages.NetworkMessageTypes.GetAppointments, appointmentArgs)); 
        }

        public void addPatientMethod(string sNumerek, string sFirstName, string sLastName,
            DateTime dAppointmentTime, int sVisitTime, int ID, string sPesel)
        {
            string sAppointmentTime = dAppointmentTime.Year + "." + dAppointmentTime.Month + "." +
                dAppointmentTime.Day + " " + dAppointmentTime.Hour + ":" + dAppointmentTime.Minute;
            ListViewItem aItem = new ListViewItem(sNumerek.ToString());
            ListViewItem.ListViewSubItem aSubItem1 = new ListViewItem.ListViewSubItem(aItem, sFirstName);
            ListViewItem.ListViewSubItem aSubItem2 = new ListViewItem.ListViewSubItem(aItem, sLastName);
            ListViewItem.ListViewSubItem aSubItem3 = new ListViewItem.ListViewSubItem(aItem, sAppointmentTime);
            ListViewItem.ListViewSubItem aSubItem4 = new ListViewItem.ListViewSubItem(aItem, sVisitTime.ToString());
            ListViewItem.ListViewSubItem aSubItem5 = new ListViewItem.ListViewSubItem(aItem, sPesel);
            ListViewItem.ListViewSubItem aSubItem6 = new ListViewItem.ListViewSubItem(aItem, ID.ToString()); 
            aItem.SubItems.Add(aSubItem1);
            aItem.SubItems.Add(aSubItem2);
            aItem.SubItems.Add(aSubItem3);
            aItem.SubItems.Add(aSubItem4);
            aItem.SubItems.Add(aSubItem5);
            aItem.SubItems.Add(aSubItem6);
            this.patientsLV.Items.Add(aItem);
        }

        public void addPatientToPatientsLV(object oSender, EventArgs oEventArgs)
        {
            ChangingArgs oAddingArgs = oEventArgs as ChangingArgs;

            int numerek = this.patientsLV.Items.Count + 1;
            this.addPatientMethod(numerek.ToString(), oAddingArgs.FirstName, oAddingArgs.LastName,
                oAddingArgs.AppointmentTime, oAddingArgs.VisitTime, -1, oAddingArgs.Pesel);
        }

        public void editPatientInPatientsLV(object oSender, EventArgs oEventArgs)
        {
            ChangingArgs oEditingArgs = oEventArgs as ChangingArgs;

            foreach (ListViewItem lvItem in this.patientsLV.SelectedItems)
            {
                string sAppointmentTime = oEditingArgs.AppointmentTime.Year + "." + oEditingArgs.AppointmentTime.Month + 
                    "." + oEditingArgs.AppointmentTime.Day + " " + oEditingArgs.AppointmentTime.Hour + ":" + 
                    oEditingArgs.AppointmentTime.Minute;

                lvItem.SubItems[1].Text = oEditingArgs.FirstName;
                lvItem.SubItems[2].Text = oEditingArgs.LastName;
                lvItem.SubItems[3].Text = sAppointmentTime;
                lvItem.SubItems[4].Text = oEditingArgs.VisitTime.ToString();
                lvItem.SubItems[5].Text = oEditingArgs.Pesel;
            }
        }

        private void addButton_Click(object sender, EventArgs e)
        {
            this.addPatientForm = new AddPatient(calendar.SelectionStart);
            addPatientForm.AddingDone += this.addPatientToPatientsLV;
            if (this.addPatientForm.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                changes = true;
            }
        }

        private void editButton_Click(object sender, EventArgs e)
        {
            if (this.patientsLV.SelectedItems.Count == 1)
            {
                foreach(ListViewItem lvItems in this.patientsLV.SelectedItems)
                {
                    this.editPatientForm = new EditPatient(lvItems.SubItems[1].Text, lvItems.SubItems[2].Text, lvItems.SubItems[3].Text, Int32.Parse(lvItems.SubItems[4].Text), lvItems.SubItems[5].Text);
                    editPatientForm.EditingDone += this.editPatientInPatientsLV;
                    editPatientForm.ShowDialog();
                }
            }
            else
            {
                MessageBox.Show("Zaznacz dokładnie jednego pacjenta.", "Błąd edycji",
                MessageBoxButtons.OK, MessageBoxIcon.Warning,
                MessageBoxDefaultButton.Button1);
            }
        }

        private void client_formClosed(object sender, FormClosedEventArgs e)
        {
        }

        private void deleteButton_Click(object sender, EventArgs e)
        {
            if (this.patientsLV.SelectedItems.Count > 0)
            {
                DialogResult reply = MessageBox.Show("Czy napęwno chesz usunąć zaznaczonych pacjentów z kolejki?", 
                   "Usuwanie pacjentów z kolejki.", MessageBoxButtons.YesNo, MessageBoxIcon.Question,
                   MessageBoxDefaultButton.Button1);

                if (reply == DialogResult.Yes)
                {
                    foreach(ListViewItem lvItem in patientsLV.SelectedItems)
                    {
                        this.patientsLV.Items.Remove(lvItem);
                    }
                    int i = 1;
                    foreach (ListViewItem item in patientsLV.Items)
                    {
                        ListViewItem.ListViewSubItem subItem = new ListViewItem.ListViewSubItem(item, i.ToString());
                        item.SubItems[0] = subItem;
                        i++;
                    }
                }
                else
                {
                    // Do nothing.
                }
            }
        }

        private void upButton_Click(object sender, EventArgs e)
        {
            if (patientsLV.SelectedItems.Count > 0)
            {
                foreach (ListViewItem listViewItem in this.patientsLV.SelectedItems)
                {
                    int pozycja = patientsLV.Items.IndexOf(listViewItem);
                    ListViewItem tempListViewItem = this.patientsLV.Items[pozycja - 1];
                    this.patientsLV.Items.Remove(listViewItem);
                    this.patientsLV.Items.Remove(tempListViewItem);
                    
                    // zamiana numerków
                    string numerekPoprzednika = tempListViewItem.SubItems[0].Text;
                    string numerekNastepnika = listViewItem.SubItems[0].Text;
                    ListViewItem.ListViewSubItem subItem = new ListViewItem.ListViewSubItem(listViewItem, numerekPoprzednika);
                    ListViewItem.ListViewSubItem tempSubItem = new ListViewItem.ListViewSubItem(tempListViewItem, numerekNastepnika);
                    listViewItem.SubItems[0] = subItem;
                    tempListViewItem.SubItems[0] = tempSubItem;

                    this.patientsLV.Items.Insert(pozycja - 1, listViewItem);
                    this.patientsLV.Items.Insert(pozycja, tempListViewItem);
                }
            }
        }

        private void itemSelectionChanged(object sender, ListViewItemSelectionChangedEventArgs e)
        {
            if (this.patientsLV.SelectedItems.Count > 0)
            {
                this.deleteButton.Enabled = true;
                if (this.patientsLV.SelectedItems.Count == 1)
                {
                    this.editButton.Enabled = true;
                    foreach (ListViewItem lvi in this.patientsLV.SelectedItems)
                    {
                        if (lvi.Index == 0)
                        {
                            this.upButton.Enabled = false;
                            this.downButton.Enabled = true;
                        }
                        else if (lvi.Index == patientsLV.Items.Count - 1)
                        {
                            this.downButton.Enabled = false;
                            this.upButton.Enabled = true;
                        }
                        else
                        {
                            this.downButton.Enabled = true;
                            this.upButton.Enabled = true;
                        }
                    }
                }
                else
                {
                    this.downButton.Enabled = false;
                    this.upButton.Enabled = false;
                    this.editButton.Enabled = false;
                }
            }
            else
            {
                this.downButton.Enabled = false;
                this.upButton.Enabled = false;
                this.deleteButton.Enabled = false;
                this.editButton.Enabled = false;
            }
        }

        private void downButton_Click(object sender, EventArgs e)
        {
            if (patientsLV.SelectedItems.Count > 0)
            {
                foreach (ListViewItem listViewItem in this.patientsLV.SelectedItems)
                {
                    int pozycja = patientsLV.Items.IndexOf(listViewItem);
                    ListViewItem tempListViewItem = this.patientsLV.Items[pozycja + 1];
                    this.patientsLV.Items.Remove(listViewItem);
                    this.patientsLV.Items.Remove(tempListViewItem);

                    // zamiana numerków
                    string numerekNastepnika = tempListViewItem.SubItems[0].Text;
                    string numerekPoprzednika = listViewItem.SubItems[0].Text;
                    ListViewItem.ListViewSubItem subItem = new ListViewItem.ListViewSubItem(listViewItem, numerekNastepnika);
                    ListViewItem.ListViewSubItem tempSubItem = new ListViewItem.ListViewSubItem(tempListViewItem, numerekPoprzednika);
                    listViewItem.SubItems[0] = subItem;
                    tempListViewItem.SubItems[0] = tempSubItem;

                    this.patientsLV.Items.Insert(pozycja, tempListViewItem);
                    this.patientsLV.Items.Insert(pozycja + 1, listViewItem);
                }
            }
        }

        private void calendar_dateSelected(object sender, DateRangeEventArgs e)
        {
            if (changes)
            {
                if (MessageBox.Show("Lista zawiera nie zapisane zmiany. Czy chcesz je zapisać?", "Nie zapisane zmiany", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == System.Windows.Forms.DialogResult.Yes)
                {
                    Cursor = Cursors.WaitCursor;
                    SaveChanges();
                    Cursor = Cursors.Arrow;
                }
            }
            if (calendar.SelectionStart > DateTime.Today)
            {
                this.infoLabel.Text = "Wyświetlona lista prezentuje listę pacjentów z dnia " + calendar.SelectionStart.Day + "." + calendar.SelectionStart.Month + "." + calendar.SelectionStart.Year;
                this.getAppointments(calendar.SelectionStart);
            }
            else if (calendar.SelectionStart == DateTime.Today)
            {
                this.infoLabel.Text = "Wyświetlona lista prezentuje listę pacjentów z dnia dzisiejszego.";
                this.getAppointments(DateTime.Today);
            }
            else
            {
                MessageBox.Show("Zaznaczono nieprawidłową datę (data wcześniejsza od obcenej)", "Wybór daty rejestracji",
                        MessageBoxButtons.OK, MessageBoxIcon.Error,
                        MessageBoxDefaultButton.Button1);
            }
        }

        private void startButton_Click(object sender, EventArgs e)
        {
            this.stopButton.Enabled = true;
            if (this.startButton.Text == "Początek pracy")
            {
                this.infoLabel.Text = "Praca rozpoczęta, aby przyjąć pierwszą osobę z listy naciśnij przycisk Następny pacjent.";
                this.startButton.Text = "Następny pacjent";
                Network.Messages.NetworkMessage sessionStartObject = new Network.Messages.NetworkMessage(Network.Messages.NetworkMessageTypes.Session_Start, -1);
                networkCC.C.Send(sessionStartObject);

                List<DisplayBoardInfo.Network.Messages.Content.Appointment> appointmentList = new List<DisplayBoardInfo.Network.Messages.Content.Appointment>();
                foreach (ListViewItem lvItem in this.patientsLV.Items)
                {
                    DisplayBoardInfo.Network.Messages.Content.Appointment appointment = new Network.Messages.Content.Appointment();
                    appointment.Number = Int32.Parse(lvItem.Text);
                    appointment.Date = DateTime.Parse(lvItem.SubItems[3].Text);
                    appointment.Doctor = this.user;
                    appointment.ExpectedTime = Int32.Parse(lvItem.SubItems[4].Text);
                    appointment.ID = Int32.Parse(lvItem.SubItems[6].Text);
                    Network.Messages.Content.Patient newPatient = new Network.Messages.Content.Patient();
                    newPatient.ID = -1;
                    newPatient.Name = lvItem.SubItems[1].Text;
                    newPatient.LastName = lvItem.SubItems[2].Text;
                    newPatient.PESEL = lvItem.SubItems[5].Text;
                    appointment.Patient = newPatient;
                    appointmentList.Add(appointment);
                }
                Network.Messages.NetworkMessage changeList_object = new Network.Messages.NetworkMessage(Network.Messages.NetworkMessageTypes.Session_ChangeList, appointmentList);
            }
            else
            {
                bool isPierwszy = true;
                List<DisplayBoardInfo.Network.Messages.Content.Appointment> appointmentList = new List<DisplayBoardInfo.Network.Messages.Content.Appointment>();
                foreach (ListViewItem lvItem in this.patientsLV.Items)
                {
                    DisplayBoardInfo.Network.Messages.Content.Appointment appointment = new Network.Messages.Content.Appointment();
                    appointment.Number = Int32.Parse(lvItem.Text);
                    appointment.Date = DateTime.Parse(lvItem.SubItems[3].Text);
                    appointment.Doctor = this.user;
                    appointment.ExpectedTime = Int32.Parse(lvItem.SubItems[4].Text);
                    appointment.ID = Int32.Parse(lvItem.SubItems[6].Text);
                    Network.Messages.Content.Patient newPatient = new Network.Messages.Content.Patient();
                    newPatient.ID = -1;
                    newPatient.Name = lvItem.SubItems[1].Text;
                    newPatient.LastName = lvItem.SubItems[2].Text;
                    newPatient.PESEL = lvItem.SubItems[5].Text;
                    appointment.Patient = newPatient;
                    appointmentList.Add(appointment);
                    if (isPierwszy)
                    {
                        isPierwszy = false;
                        this.infoLabel.Text = "W tej chwili przyjmujesz: " + appointment.Patient.Name + " " + appointment.Patient.LastName + ". Przywidziany czas wizyty to: " + appointment.ExpectedTime;
                    }
    
                }
                Network.Messages.NetworkMessage sessionNextPatientObject = new Network.Messages.NetworkMessage(Network.Messages.NetworkMessageTypes.Session_NextPatient, appointmentList);
                this.patientsLV.Items.RemoveAt(0);
                networkCC.C.Send(sessionNextPatientObject);
                
            }
        }

        private void stopButton_Click(object sender, EventArgs e)
        {
            this.stopButton.Enabled = false;
            this.infoLabel.Text = "Właśnie zakończyłeś pracę. Możesz teraz wyłączyć aplikacje.";
            this.startButton.Text = "Początek pracy";
            Network.Messages.NetworkMessage sessionEndObject = new Network.Messages.NetworkMessage(Network.Messages.NetworkMessageTypes.Session_End, -1);
            networkCC.C.Send(sessionEndObject);
        }

        private void pauseButton_Click(object sender, EventArgs e)
        {
            if (pauseButton.Text == "Przerwa")
            {
                PauseReason pauseReason = new PauseReason();
                if (pauseReason.ShowDialog() == System.Windows.Forms.DialogResult.OK)
                {
                    this.reason = pauseReason.Reason;
                    Network.Messages.NetworkMessage sessionPause = new Network.Messages.NetworkMessage(Network.Messages.NetworkMessageTypes.Session_Pause, reason);
                    networkCC.C.Send(sessionPause);
                    this.pauseButton.Text = "Kontynuacja";
                    this.infoLabel.Text = "W tej chwili znajdujesz się w trybie przerwy";
                }
            }
            else
            {
                Network.Messages.NetworkMessage sessionPause = new Network.Messages.NetworkMessage(Network.Messages.NetworkMessageTypes.Session_Start, "");
                networkCC.C.Send(sessionPause);
                this.infoLabel.Text = "Przerwa zakończona. Kliknij na przycisk Następny pacjent, aby kontynuować pracę.";
                this.pauseButton.Text = "Przerwa";
            }
        }

        private void saveButton_Click(object sender, EventArgs e)
        {
            SaveChanges();
        }

        private void SaveChanges()
        {
            List<DisplayBoardInfo.Network.Messages.Content.Appointment> appointmentList = new List<DisplayBoardInfo.Network.Messages.Content.Appointment>();
            foreach (ListViewItem lvItem in this.patientsLV.Items)
            {
                DisplayBoardInfo.Network.Messages.Content.Appointment appointment = new Network.Messages.Content.Appointment();
                appointment.Number = Int32.Parse(lvItem.Text);
                appointment.Date = DateTime.Parse(lvItem.SubItems[3].Text);
                appointment.Doctor = this.user;
                appointment.ExpectedTime = Int32.Parse(lvItem.SubItems[4].Text);
                appointment.ID = Int32.Parse(lvItem.SubItems[6].Text);
                Network.Messages.Content.Patient newPatient = new Network.Messages.Content.Patient();
                newPatient.ID = -1;
                newPatient.Name = lvItem.SubItems[1].Text;
                newPatient.LastName = lvItem.SubItems[2].Text;
                newPatient.PESEL = lvItem.SubItems[5].Text;
                appointment.Patient = newPatient;
                appointmentList.Add(appointment);
            }
            Network.Messages.NetworkMessage sessionChangeListObject = new Network.Messages.NetworkMessage(Network.Messages.NetworkMessageTypes.AddAppointment, appointmentList);
            networkCC.C.Send(sessionChangeListObject);
        }

        private void infoLabel_Click(object sender, EventArgs e)
        {

        }

        private void updateButton_Click(object sender, EventArgs e)
        {
            List<DisplayBoardInfo.Network.Messages.Content.Appointment> appointmentList = new List<DisplayBoardInfo.Network.Messages.Content.Appointment>();
            foreach (ListViewItem lvItem in this.patientsLV.Items)
            {
                DisplayBoardInfo.Network.Messages.Content.Appointment appointment = new Network.Messages.Content.Appointment();
                appointment.Number = Int32.Parse(lvItem.Text);
                appointment.Date = DateTime.Parse(lvItem.SubItems[3].Text);
                appointment.Doctor = this.user;
                appointment.ExpectedTime = Int32.Parse(lvItem.SubItems[4].Text);
                appointment.ID = Int32.Parse(lvItem.SubItems[6].Text);
                Network.Messages.Content.Patient newPatient = new Network.Messages.Content.Patient();
                newPatient.ID = -1;
                newPatient.Name = lvItem.SubItems[1].Text;
                newPatient.LastName = lvItem.SubItems[2].Text;
                newPatient.PESEL = lvItem.SubItems[5].Text;
                appointment.Patient = newPatient;
                appointmentList.Add(appointment);

            }
            Network.Messages.NetworkMessage sessionNextPatientObject = new Network.Messages.NetworkMessage(Network.Messages.NetworkMessageTypes.Session_ChangeList, appointmentList);
            networkCC.C.Send(sessionNextPatientObject);
        }

    }

    public class ChangingArgs : EventArgs
    {
        public string FirstName { get; private set; }
        public string LastName { get; private set; }
        public DateTime AppointmentTime { get; private set; }
        public int VisitTime { get; private set; }
        public string Pesel { get; private set; }

        public ChangingArgs(string sFirstName, string sLastName,
            DateTime dAppointmentTime, int sVisitTime, string sPesel)
        {
            FirstName = sFirstName;
            LastName = sLastName;
            AppointmentTime = dAppointmentTime;
            VisitTime = sVisitTime;
            Pesel = sPesel;
        }
    }

}
